---
title: 受控编辑器值
description: 如何控制编辑器的值。
---

在 Plate 中实现完全受控的编辑器值较为复杂，原因如下：

1. 编辑器状态不仅包含内容 (`editor.children`)，还包含 `editor.selection` 和 `editor.history`。

2. 直接替换 `editor.children` 可能会破坏选区(selection)和历史记录(history)，导致意外行为或崩溃。

3. 所有对编辑器值的更改都应通过 [Transforms](https://docs.slatejs.org/api/transforms) 进行，以保持与选区(selection)和历史记录(history)的一致性。

鉴于这些挑战，通常建议将 Plate 作为非受控输入使用。但如果需要从外部更改编辑器内容，可以使用 `editor.tf.setValue(value)` 函数。

<Callout type="warning" title="性能考量">
  使用 `editor.tf.setValue` 会在每次调用时重新渲染所有节点，因此应谨慎使用。
  如果频繁调用或处理大型文档，可能会影响性能。
</Callout>

或者，您可以使用 `editor.tf.reset()` 来重置编辑器状态，这将同时重置选区(selection)和历史记录(history)。

### 异步初始值

您可以使用 `skipInitialization` 延迟编辑器初始化，直到异步数据准备就绪。然后调用 `editor.tf.init` 并传入您的值：

```tsx
function AsyncControlledEditor() {
  const [initialValue, setInitialValue] = React.useState();
  const [loading, setLoading] = React.useState(true);
  const editor = usePlateEditor({
    skipInitialization: true,
  });

  React.useEffect(() => {
    // 模拟异步获取
    setTimeout(() => {
      setInitialValue([
        {
          type: 'p',
          children: [{ text: '已加载异步值！' }],
        },
      ]);
      setLoading(false);
    }, 1000);
  }, []);

  React.useEffect(() => {
    if (!loading && initialValue) {
      editor.tf.init({ value: initialValue, autoSelect: 'end' });
    }
  }, [loading, initialValue, editor]);

  if (loading) return <div>加载中…</div>;

  return (
    <Plate editor={editor}>
      <EditorContainer>
        <Editor />
      </EditorContainer>
    </Plate>
  );
}
```

<ComponentPreview name="controlled-demo" padding="md" />